#include "geminai_CH455.h"

#define H 0x76
#define I 0x06
#define L 0x38
#define C 0x39
#define E 0x79
#define F 0x71
#define O 0x3F
#define d 0x5e
#define r 0x50
#define openLed 0x40
#define closeLed 0x5c

#define I2C_SDA_GPIO   39  // 更改为你的 SDA 引脚
#define I2C_SCL_GPIO   38  // 更改为你的 SCL 引脚

#define I2C_DELAY_US   50  // 延迟时间，单位为纳秒5

#define I2C_MASTER_SCL_IO           38      /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO           37      /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_NUM              1                          /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ          400000                     /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS       1000

//设置系统参数
#define CH455_SYS       0x48            //设置系统参数
#define CH455_KEYOFF    0X80            //禁用键盘扫描
#define CH455_ENABLE    0x01            //使能显示驱动与键盘

// 加载字数据命令

#define CH455_DIG0		0x68			// 个位
#define CH455_DIG1		0x6A			// 十位/使用小数点时与DP相或,(bcdcode[x] | DP)
#define CH455_DIG2		0x6C			// 百位
#define CH455_DIG3		0x6E		// 符号位

//0-f
static uint8_t numcode[16]={ 0X3F, 0X06, 0X5B, 0X4F, 0X66, 0X6D, 0X7D, 0X07, 0X7F, 0X6F,0X77, 0X7C, 0X58, 0X5E, 0X79, 0X71}; 

// 定义 I2C 时序
#define SDA_HIGH()    gpio_set_level(I2C_SDA_GPIO, 1)
#define SDA_LOW()     gpio_set_level(I2C_SDA_GPIO, 0)
#define SCL_HIGH()    gpio_set_level(I2C_SCL_GPIO, 1)
#define SCL_LOW()     gpio_set_level(I2C_SCL_GPIO, 0)
#define SDA_READ()    gpio_get_level(I2C_SDA_GPIO)

// 延迟函数
void delay_us(uint32_t us) {
    usleep(us);
}

// 初始化 I2C 模拟
void i2c_sim_init() {
    gpio_config_t io_conf;
    
    // 配置 SDA 引脚
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = (1ULL << I2C_SDA_GPIO);
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
    gpio_config(&io_conf);
    
    // 配置 SCL 引脚
    io_conf.pin_bit_mask = (1ULL << I2C_SCL_GPIO);
    gpio_config(&io_conf);
}

// 发送 START 信号
void i2c_sim_start() {
    SDA_HIGH();
    SCL_HIGH();
    delay_us(I2C_DELAY_US);
    SDA_LOW();
    delay_us(I2C_DELAY_US);
    SCL_LOW();
}

// 发送 STOP 信号
void i2c_sim_stop() {
    SDA_LOW();
    SCL_HIGH();
    delay_us(I2C_DELAY_US);
    SDA_HIGH();
    delay_us(I2C_DELAY_US);
}

// 发送一个字节
void i2c_sim_write_byte(uint8_t data) {
    for (int i = 0; i < 8; i++) {
        if (data & 0x80) {
            SDA_HIGH();
        } else {
            SDA_LOW();
        }
        delay_us(I2C_DELAY_US);
        SCL_HIGH();
        delay_us(I2C_DELAY_US);
        SCL_LOW();
        data <<= 1;
    }
    // 发送 ACK
    SDA_HIGH();
    delay_us(I2C_DELAY_US);
    SCL_HIGH();
    delay_us(I2C_DELAY_US);
    SCL_LOW();
}

// 读取一个字节
uint8_t i2c_sim_read_byte() {
    uint8_t data = 0;
    SDA_HIGH();
    for (int i = 0; i < 8; i++) {
        SCL_HIGH();
        delay_us(I2C_DELAY_US);
        data <<= 1;
        if (SDA_READ()) {
            data |= 0x01;
        }
        SCL_LOW();
        delay_us(I2C_DELAY_US);
    }
    return data;
}

// 发送 ACK
void i2c_sim_send_ack() {
    SDA_LOW();
    delay_us(I2C_DELAY_US);
    SCL_HIGH();
    delay_us(I2C_DELAY_US);
    SCL_LOW();
}

// 发送 NACK
void i2c_sim_send_nack() {
    SDA_HIGH();
    delay_us(I2C_DELAY_US);
    SCL_HIGH();
    delay_us(I2C_DELAY_US);
    SCL_LOW();
}

void CH455_Write(uint8_t cmd,uint8_t data)
{
    i2c_sim_start();
    i2c_sim_write_byte(cmd);
    i2c_sim_write_byte(data);
    i2c_sim_stop();
}

void CH455_Init()
{
    i2c_sim_init();
    CH455_Write(CH455_SYS, CH455_ENABLE | CH455_KEYOFF);    
    brightness_adjustment(7);
    digital_display(0,0);
}

void digital_display(float temp,uint8_t state)
{
    uint8_t  mask = state;
    if(temp<0)
    {
        mask |= CH_MINUS;
        temp=-temp;
    }
    if(temp == 0xfb || temp == 0xfa || temp == 0xfc ||  temp == 0xfe || temp == 0xff )
        mask |= CH_ALARM;
    CH455_Write(CH455_DIG3,mask);

         if(temp ==0xfb) { CH455_Write(CH455_DIG2,H); CH455_Write(CH455_DIG1,I); CH455_Write(CH455_DIG0,0x00); }    //Hi 高温报警
    else if(temp ==0xfa) { CH455_Write(CH455_DIG2,L); CH455_Write(CH455_DIG1,O); CH455_Write(CH455_DIG0,0x00); }    //LO 低温报警
    else if(temp ==0xfc) { CH455_Write(CH455_DIG2,d); CH455_Write(CH455_DIG1,r); CH455_Write(CH455_DIG0,0x00); }    //dr 开门报警
    else if(temp ==0xfd) { CH455_Write(CH455_DIG2,d); CH455_Write(CH455_DIG1,F); CH455_Write(CH455_DIG0,0x00); }    //dF 除霜
    else if(temp ==0xf8) { CH455_Write(CH455_DIG2,C); CH455_Write(CH455_DIG1,C); CH455_Write(CH455_DIG0,0x00); }    //CC 强制制冷
    else if(temp ==0xf9) { CH455_Write(CH455_DIG2,O); CH455_Write(CH455_DIG1,F); CH455_Write(CH455_DIG0,F);}        //OFF 制冷关闭
    else if(temp ==0xf7) { CH455_Write(CH455_DIG2,L); CH455_Write(CH455_DIG1,O); CH455_Write(CH455_DIG0,C);}        //LOC 锁机    
    else if(temp ==0xfe) { CH455_Write(CH455_DIG2,E); CH455_Write(CH455_DIG1,numcode[1]); CH455_Write(CH455_DIG0,0x00); }    //E1 温探头1异常
    else if(temp ==0xff) { CH455_Write(CH455_DIG2,E); CH455_Write(CH455_DIG1,numcode[2]); CH455_Write(CH455_DIG0,0x00); }    //E2 温探头2异常
    else if(temp ==0xf6) { CH455_Write(CH455_DIG2,0x00); CH455_Write(CH455_DIG1,openLed); CH455_Write(CH455_DIG0,0x00); }    //- 开灯
    else if(temp ==0xf5) { CH455_Write(CH455_DIG2,0x00); CH455_Write(CH455_DIG1,closeLed); CH455_Write(CH455_DIG0,0x00); }    //o 关灯
    else
    {
        int num = (int)(temp*10);        
        CH455_Write(CH455_DIG0,numcode[num%10]);
        CH455_Write(CH455_DIG1,numcode[num/10%10]|CH_DP);
        if(temp>10)
            CH455_Write(CH455_DIG2,numcode[num/100%10]);
        else
            CH455_Write(CH455_DIG2,0x00);
    }  
}

void brightness_adjustment(int value)
{
    if(value<=0 || value>8)
        return;
    int para = 0;
    para = (value << 4) | CH455_ENABLE | CH455_KEYOFF;
    CH455_Write(CH455_SYS, para);
}
